<template>
  <div class="container">
    <!-- 基本用法 -->
    <div class="panel">
      <div class="header">基本用法</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <!-- :data="basicUsage" -->
            <CTree
              ref="treeRef"
              
              title-field="name"
              :nodeClassName="(node) => `generated-class-${node.id}`"
              selectable
              :size="'mini'"
              :showLine="true"
              animation
            >
              <!-- 两种都行 -->
              <template v-slot="{ node }">
                <div class="custom-tree-node-1" style="color: red;">
                  {{ node.name }} === {{ node.isLeaf }}
                </div>
              </template>
              
              <!-- <template v-slot:node="{ node }">
                <span class="custom-tree-node-2" style="color: red;">
                  {{ node.name }}
                </span>
              </template> -->
            </CTree>
          </div>
        </div>
        <div class="desc">
          纯展示
        </div>
      </div>
    </div>

    <!-- 数据正确性验证 -->
    <div class="panel">
      <div class="header">数据正确性验证</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <CTree
              :data="orderData"
              default-expand-all
              selectable
              animation
            ></CTree>
          </div>
        </div>
        <div class="desc">
          数据正确性
        </div>
      </div>
    </div>

    <!-- 单选 -->
    <div class="panel">
      <div class="header">单选</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <CTree
              v-model="selectableValue"
              :data="selectable"
              selectable
            ></CTree>
          </div>
        </div>
        <div class="desc">
          单选模式。设置 selectable 即可<br/>
          v-model: <br/>
          {{ selectableValue }}
        </div>
      </div>
    </div>

    <!-- 多选 -->
    <div class="panel">
      <div class="header">多选</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <CTree
              v-if="showCheckable"
              v-model="checkableValue"
              :data="checkable"
              checkable
              :ignore-mode="checkableIgnoreMode"
              :cascade="checkableCascade"
              :showLine="true"
            ></CTree>
          </div>
        </div>
        <div class="desc">
          <div class="desc-block">
            <p>多选模式。设置 checkable 即可</p>
            v-model: <br/>
            {{ checkableValue }}
          </div>
          <div class="desc-block">
            <p>设置 ignoreMode 可指定 v-model 与 getCheckedNodes 方法要忽略父节点或者子节点，该 prop 仅初始设置有效</p>
            <button
              v-for="mode in ['none', 'parents', 'children']"
              :key="mode"
              @click="checkableIgnoreMode = mode; showCheckable = false; $nextTick(() => { checkableValue = []; showCheckable = true })"
            >{{ mode }}</button>
            <p>当前 ignoreMode: {{ checkableIgnoreMode }}</p>
          </div>
          <div class="desc-block">
            <p>设置 cascade 可指定父子节点是否级联</p>
            <button
              v-for="(mode, index) in [true, false]"
              :key="index"
              @click="checkableCascade = mode; showCheckable = false; $nextTick(() => { checkableValue = []; showCheckable = true })"
            >{{ mode }}</button>
            <p>当前 cascade: {{ checkableCascade }}</p>
          </div>
          <div class="desc-block">
            <p>重置以上选项</p>
            <button
              @click="
              showCheckable = false;
              $nextTick(() => {
                checkableIgnoreMode = 'none';
                checkableCascade = true;
                checkableValue = [];
                showCheckable = true
              })"
            >Reset</button>
          </div>
        </div>
      </div>
    </div>

    <!-- 单选与多选并存 -->
    <div class="panel">
      <div class="header">单选与多选并存</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <CTree
              v-model="bothValue"
              :data="both"
              checkable
              selectable
              animation
              :showLine="{
                type: 'dashed',
                polyline: false,
                dashDensity: 3,
              }"
            ></CTree>
          </div>
        </div>
        <div class="desc">
          当既可以单选又可以多选时， v-model 绑定的是多选的值<br/>
          v-model: <br/>
          {{ bothValue }}
        </div>
      </div>
    </div>

    <!-- 远程 -->
    <div class="panel">
      <div class="header">远程</div>
      <div class="body">
        <div class="interface">
          <div style="height: 300px;">
            <CTree
              v-if="remoteShow"
              :load="remoteLoad"
            ></CTree>
          </div>
        </div>
        <div class="desc">
          <div class="desc-block">
            设置 load 方法可以使用远程加载数据，如果有设置 data ，则 data 数据作为根数据；<br/>
            如果没有传 data ，则初始化时调用 load 方法载入根数据，其中节点参数为 null
          </div>
          <div class="desc-block">
            <button
              @click="remoteShow = false; $nextTick(() => { remoteShow = true })"
            >加载树组件</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import CTree from '@'
import treeDataGenerator from '../tests/tree-data-generator'

function buildTree(data, root = '', isClone = false) {
    if (!Array.isArray(data)) {
        throw Error('The list parameter must be an array.')
    }

    console.time('🌳BuildTree')
    // 暂时不拷贝新的 data; 需注意目前会改变原数据
    // let newData = deepClone(data)

    if (isClone) {
        data = deepClone(data)
    }

    // 用于存放 list 下的节点
    const map = {}
    // 用于存放最终结果
    const result = []

    // 1.遍历 list, 将list下的所有节点以id作为索引存入 map
    for (let i = 0; i < data.length; i++) {
        const item = data[i]
        if (!map[item.id]) {
            map[item.id] = item
        }
    }

    // 2.再次遍历, 将根节点放入最外层, 子节点放入父节点
    for (let k = 0; k < data.length; k++) {
        const item = data[k]
        // 3.如果是根节点, 则存入 result; 反之存入父节点
        // console.log(Object.hasOwn(map, item.pid))
        if (map[item.pid] && map[item.pid] !== root) {
            // 对子节点数组进行中文排序
            // if (!map[item.pid].children) {
            //     map[item.pid].children = []
            // }
            // map[item.pid].children.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'))

            map[item.pid].children = map[item.pid].children || []
            map[item.pid].children.push(item)
        } else {
            result.push(map[item.id])
        }
    }

    console.timeEnd('🌳BuildTree')
    return result
}

const genData = (extra = {}) => {
  return treeDataGenerator(Object.assign({
    treeDepth: 3,
    nodesPerLevel: 5,
    sameIdTitle: true,
  }, extra))
}

const genChildrenData = (nodeCount = 2) => {
  return treeDataGenerator({
    treeDepth: 1,
    nodesPerLevel: nodeCount,
    inOrder: true,
  })
}

export default {
  name: 'Feature',
  components: {
    CTree,
  },
  data () {
    const selectableData = genData().data
    selectableData[0].selected = true
    const checkableData = genData().data
    checkableData[0].expand = true
    checkableData[1].children[0].disabled = true
    // checkableData[1].children[0].children[0].checked = true

    return {
      // 基本用法
      basicUsage: genData().data,

      // 数据正确性
      orderData: genData({ inOrder: true }).data,

      // 单选
      selectable: selectableData,
      // selectableValue: selectableData[0].id,
      selectableValue: '',

      // 多选
      showCheckable: true,
      checkable: checkableData,
      checkableValue: [checkableData[0].id],
      checkableIgnoreMode: 'none',
      checkableCascade: true,

      // 单选与多选并存
      both: genData().data,
      bothValue: [],

      // 远程
      remoteShow: false,
      remoteLoad: (node, resolve, reject) => {
        setTimeout(() => {
          resolve(genChildrenData(node ? 2 : 5).data)
        }, 1000)
      }
    }
  },
  mounted() {

    fetch('http://localhost:8803/api/organize')
      .then(res => {
        return res.json()
      })
      .then(({ data }) => {
        console.log('🚀%c ~ data:', 'color: #42b883;', data)
        const x = buildTree(data)
        console.log('🚀%c ~ x:', 'color: #42b883;', x)
        this.$refs['treeRef'].setData(x)
      })
  }
}
</script>

<style lang="less" scoped>
.container {
  width: 100%;
  height: 100%;
  padding: 10px;
  box-sizing: border-box;
  .panel {
    width: 100%;
    margin-bottom: 10px;
    border: 1px solid lightgray;
    border-radius: 5px;
    .header {
      height: 30px;
      border-bottom: 1px solid lightgray;
      padding: 10px 30px;
    }
    .body {
      display: flex;
      .interface {
        flex: 1;
        padding: 10px 30px;
        border-right: 1px solid lightgray;
      }
      .desc {
        flex: 1;
        padding: 10px 30px;
        .desc-block {
          padding: 5px 0;
          margin-bottom: 10px;
          border-bottom: 1px solid lightgray;
          &:last-child {
            border-bottom: none;
          }
        }
      }
    }
  }
}
</style>
